package myapp.camera;

import java.util.ArrayList;
import staticClass.XmppConnection;
import myapp.Chat.XmppClient;
import myapp.DTO.CategoryDTO;
import myapp.DTO.ServiceDTO;
import myapp.DTO.SubItemDTO;
import myapp.EnumAndConstans.Constants;
import myapp.database.CategoryDB;
import myapp.database.ItemDB;
import myapp.dictionary.MyDictionary;
import myapp.drawable_items.PreviewDraw;
import myapp.googlemap.GoogleMapActivity;
import myapp.googlemap.R;
import myapp.helper.NetworkHelper;
import myapp.helper.OrientationHelper;
import myapp.kalman_filter.KalmanState;
import myapp.services.DbServiceHelper;
import myapp.sortStategy.AscendingComparatorByCategory;
import myapp.sortStategy.AscendingComparatorByDistance;
import myapp.sortStategy.AscendingComparatorByName;
import myapp.sortStategy.Comparator;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.SharedPreferences.Editor;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;
import android.widget.Gallery;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class MainActivity extends Activity {

	private Context context;
	// Camera camera;
	public static CameraPreview preview;
	PreviewDraw myDraw;

	// Compass
	private Boolean isCompass = true;// De test tren may ao = false
	private Boolean changeIntent = true;
	public static Boolean autoChangeScreen = false;
	public static Boolean autoFilterServicesByOrientation = false;
	public static Boolean displayServiceIcon = false;
	public static Boolean autoUpdateLocation = true;
	public static Boolean firsTimetUse = false;
	private float[] aValues = new float[3];
	private float[] mValues = new float[3];
	private float[] oldAngleValues = { 0f, 0f, 0f };
	private SensorManager sensorManager;
	private KalmanState km0;
	private KalmanState km1;
	private KalmanState km2;
	// Compass//////////////

	private ItemDB iDB;
	private CategoryDB caDB;
	public static ArrayList<ServiceDTO> service_data_original= new ArrayList<ServiceDTO>();
	private static ArrayList<ServiceDTO> service_data_displayListService;
	private ArrayList<ServiceDTO> service_data_displayServiceIcon;
	private ArrayList<ServiceDTO> service_data_loading;
	private ArrayList<CategoryDTO> category_data;
	private ArrayList<CategoryDTO> category_data_original;	
	private ItemAdapter itemAdapter;
	private CategoryAdapter categoryAdapter;
	private static ArrayList<SubItemDTO> subItems_data = new ArrayList<SubItemDTO>();
	private static boolean bool_discount_information = false;
	
	//Filter service by category:  the array hold true/false value of each type of service 
	private static SparseBooleanArray category_selected = new SparseBooleanArray();
	
	private ListView listViewItemCamera;
	private Gallery listViewCategoryCamera;

	public static int distance_max = 100;
	public static int distance_min = 0;

	// Sort services by comparator
	private static Comparator comparator = new AscendingComparatorByDistance();

	private static ProgressDialog pd_downloadSubItem;
	private static ProgressDialog pd_downloadServices;
	
	private SharedPreferences prefs;

	private static EndlessScrollListener scrollListener;	
	private static LoadDataTask loadDataTask;	
	private LayoutInflater mInflater;
	// footer view
	private View mFooterView;
	// private TextView mLabLoadMore;
	private ProgressBar mProgressBarLoadMore;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_camera);
		context = this;

		updateFromPreferences();

		myDraw = new PreviewDraw(this);
		addContentView(myDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		myDraw.setVisibility(View.GONE);
		myDraw.setVisibility(View.VISIBLE);
		myDraw.setMaxDistance(distance_max);
		
		preview = new CameraPreview(this);

		Log.i("MainActivity", "[onCreate] preview");
		
		FrameLayout layout = ((FrameLayout) findViewById(R.id.preview));
		layout.addView(preview);

		// /////Khoi tao
		// datebase////////////////////////////////////////////////////////////
		caDB = new CategoryDB(this);


		/*
		 * Get categories
		 */
		category_data = new ArrayList<CategoryDTO>();
		category_data.add(new CategoryDTO(-1, "All services"));
		try
		{
			caDB.open();
			category_data_original = caDB.getAllCategories();
			category_data.addAll(category_data_original);
		caDB.close();
		}catch(Exception e){}
		
		iDB = new ItemDB(this);
		
		  /*iDB.open(); 
		  iDB.insertItem(67,"Khách Sạn Equatorial", 1,
		  (float)106.6791182756424, (float)10.763254191089795,
		  "242 Đường Trần Bình Trọng, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38397777 - 08.38390000", "Tiêu Chuẩn 5 Sao, 333 Phòng");
		  iDB.insertItem(1,"Khách Sạn Caravelle", 1, (float)106.703542470932,
		  (float)10.776039044190476,
		  "19-23 Đường Công Trường Lam Sơn, Phường Bến Nghé, Quận 1, Thành Phố Hồ Chí Minh"
		  , "08.38234999", "Tiêu Chuẩn 5 Sao, 335 Phòng");
		  iDB.insertItem(2,"Coffee Restaurant Thảo Chi", 2,
		  (float)106.68163418769836, (float)10.766342420476446,
		  "21/1 Đường Nguyễn Thiện Thuật, Phường 2, Quận 3, Thành Phố Hồ Chí Minh"
		  , "08.38356167", null);
		  
		  iDB.insertItem(3,"Nhà Hàng Mỹ Hảo", 2, (float)106.67796492576599,
		  (float)10.761251568089827,
		  "83 Đường Trần Phú, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38355087", "Các Món Đặc Sản Âu Á");
		  iDB.insertItem(4,"Nhà Hàng Phương Ngọc", 2,
		  (float)106.67975664138794, (float)10.763591473654328,
		  "8 Đường Trần Phú, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38300514 - 08.38300514", null);
		  iDB.insertItem(5,"N.Y.D.C Café & Restaurant", 2,
		  (float)10.764171177180238, (float)106.68236374855042,
		  "35 Đường Nguyễn Văn Cừ, Phường Nguyễn Cư Trinh, Quận 1, Thành Phố Hồ Chí Minh"
		  , "08.38336933", null); iDB.insertItem(6,"Nhà Hàng Hương Rừng 1", 2,
		  (float)106.6853678226471, (float)10.760155389866293,
		  "371A Đường Nguyễn Trãi, Phường Nguyễn Cư Trinh, Quận 1, Thành Phố Hồ Chí Minh"
		  , "08.39200465", null);
		  iDB.insertItem(7,"ATM - Ngân Hàng Sài Gòn Thương Tín - Sacombank", 3,
		  (float)106.6834044456482, (float)10.761146166510759,
		  "235C Đường Nguyễn Văn Cừ, Phường Nguyễn Cư Trinh, Quận 1, Thành Phố Hồ Chí Minh"
		  , null, null);
		  iDB.insertItem(8,"ATM - Ngân Hàng Sài Gòn Thương Tín - Sacombank", 3,
		  (float)106.67963862419128, (float)10.761493991581819,
		  "240 Đường Trần Bình Trọng, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  null, null); iDB.insertItem(9,"ATM - Ngân Hàng HSBC - HSBC", 3,
		  (float)106.68237447738647, (float)10.763918215778792,
		  "235 Đường Nguyễn Văn Cừ, Phường Nguyễn Cư Trinh, Quận 1, Thành Phố Hồ Chí Minh"
		  , null, null);
		  iDB.insertItem(10,"ATM - Ngân Hàng Đông Á - DongA Bank", 3,
		  (float)106.69194459915161, (float)10.764318737899709,
		  "148 Đường Trần Hưng Đạo, Phường Nguyễn Cư Trinh, Quận 1, Thành Phố Hồ Chí Minh"
		  , null,
		  "Đặt Tại Khách Sạn Metropole, Máy ATM Của DongA Bank Kết Nối Với DAIABANK"
		  );
		  
		  iDB.insertItem(11,"Bệnh Viện Từ Dũ", 4, (float)106.6853141784668,
		  (float)10.768429328898717,
		  "284 Đường Cống Quỳnh, Phường Phạm Ngũ Lão, Quận 1, Thành Phố Hồ Chí Minh"
		  , "08.54042829", null);
		  iDB.insertItem(12,"Bệnh Viện Đa Khoa Sài Gòn", 4,
		  (float)106.69928312301636, (float)10.771907477475352,
		  "125 Đường Lê Lợi, Phường Bến Thành, Quận 1, Thành Phố Hồ Chí Minh",
		  "08.38291711 - 08.38297709", null);
		  iDB.insertItem(13,"Bệnh Viện Công an 30-4", 4,
		  (float)106.67287945747375, (float)10.759248931786287,
		  "9 Đường Sư Vạn Hạnh, Phường 9, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38354986", null);
		  iDB.insertItem(14,"Bệnh Viện Chấn Thương Chỉnh Hình", 4,
		  (float)106.6781151294708, (float)10.7543002550400643,
		  "929 Đường Trần Hưng Đạo, Phường 1, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.39235791", null);
		  
		  iDB.insertItem(68,"Nhà Sách Minh Tâm", 5, (float)106.68136596679688,
		  (float)10.760503216080457,
		  "286B Đường An Dương Vương, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38353608", null);
		  iDB.insertItem(16,"Fahasa - Kho Hàng Trung Tâm Nhà Sách Nguyễn Huệ",
		  5, (float)106.69095754623413, (float)10.760998604238159,
		  "55 Đường Trần Đình Xu, Phường Cầu Kho, Quận 1, Thành Phố Hồ Chí Minh"
		  , "08.39202509", null); iDB.insertItem(17,"Karaoke Vân Đồn", 6,
		  (float)106.70059204101562, (float)10.757130338902419,
		  "120-122 Đường Khánh Hội, Phường 4, Quận 4, Thành Phố Hồ Chí Minh",
		  "08.39401471", "Nhận Đặt Tiệc Cưới, Sinh Nhật, Liên Hoan");
		  iDB.insertItem(18,"Karaoke Phượng Oanh", 6,
		  (float)106.68194532394409, (float)10.766026220969675,
		  "512 Đường Nguyễn Thị Minh Khai, Phường 2, Quận 3, Thành Phố Hồ Chí Minh"
		  , null, null); iDB.insertItem(19,"Karaoke Gia Đình Ly Ly", 6,
		  (float)106.67863011360168, (float)10.757615192318589,
		  "155-157 Đường Nguyễn Trãi, Phường 2, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.39234780", null);
		  
		  iDB.insertItem(20,"Trường Đại Học Khoa Học Tự Nhiên", 7,
		  (float)106.68248176574707, (float)10.762980148728202,
		  "227 Đường Nguyễn Văn Cừ, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38353193", null);
		  iDB.insertItem(21,"Trường Trung Học Thực Hành Đại Học Sư Phạm", 7,
		  (float)106.68238520622253, (float)10.760945903409015,
		  "280 Đường An Dương Vương, Phường 4, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38303588 - 08.38352020", null);
		  iDB.insertItem(22,"Trường Đại Học Sài Gòn", 7,
		  (float)106.6836404800415, (float)10.760092148693323,
		  "205 Đường Nguyễn Văn Cừ, Phường 3, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38354409", null);
		  iDB.insertItem(69,"Trường Đại Học Y Dược Thành Phố Hồ Chí Minh", 7,
		  (float)106.66315913200378, (float)10.755138215598903,
		  "217 Đường Hồng Bàng, Phường 11, Quận 5, Thành Phố Hồ Chí Minh",
		  "08.38558411 - 08.38567645", null); iDB.close();
		  iDB.close();*/
		// //////////////////////////////////////////////////////////////////////////////////

		// Khoi tao Dictionary (thiet lap CUNG, khong thay doi). Co the tim dung
		// ten => put(id, R.)
		MyDictionary.dictionary.put(-1, R.drawable.services);
		MyDictionary.dictionary.put(1, R.drawable.hotel_icon);
		MyDictionary.dictionary.put(2, R.drawable.restaurant_icon);
		MyDictionary.dictionary.put(3, R.drawable.atm_icon1);
		MyDictionary.dictionary.put(4, R.drawable.hospital_icon);
		MyDictionary.dictionary.put(5, R.drawable.bookstore_icon);
		MyDictionary.dictionary.put(6, R.drawable.karaoke);
		MyDictionary.dictionary.put(7, R.drawable.school_icon);

		/*
		 * Khoi tao category_selected
		 */
		if (category_selected.size() == 0)
		{
			category_selected.put(1, true);
			category_selected.put(2, true);
			category_selected.put(3, true);
			category_selected.put(4, true);
			category_selected.put(5, true);
			category_selected.put(6, true);
			category_selected.put(7, true);
		}
		
		service_data_displayListService = new ArrayList<ServiceDTO>();
		service_data_displayServiceIcon = new ArrayList<ServiceDTO>();
		service_data_loading = new ArrayList<ServiceDTO>();
		
		/*
		 * Get services
		 */
		long start = System.currentTimeMillis();		
		if (service_data_original == null)	
		{
			service_data_original = new ArrayList<ServiceDTO>();
			//loadData();
		}

		long end = System.currentTimeMillis();
		Log.i("Time_LoadData", String.valueOf(end-start));

		service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
		service_data_displayServiceIcon.addAll(service_data_displayListService);
		
		if (autoFilterServicesByOrientation == true)
			itemAdapter = new ItemAdapter(this, R.layout.listview_item_camera, service_data_displayListService, subItems_data, bool_discount_information);
		else			
			itemAdapter = new ItemAdapter(this, R.layout.listview_item_camera, service_data_loading, subItems_data, bool_discount_information);
		listViewItemCamera = (ListView) findViewById(R.id.listViewItemCamera);		
		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mFooterView = (RelativeLayout) mInflater.inflate(R.layout.load_more_footer, listViewItemCamera, false);
		mProgressBarLoadMore = (ProgressBar) mFooterView.findViewById(R.id.load_more_progressBar);
		listViewItemCamera.addFooterView(mFooterView);
		listViewItemCamera.invalidate();		
		listViewItemCamera.setAdapter(itemAdapter);
		listViewItemCamera.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				if (bool_discount_information)
				{
					for (SubItemDTO sub : subItems_data)
						if (service_data_displayListService.get(position).getId() == sub.serviceId)
						{
							setViewAlert(service_data_displayListService.get(position), sub);
							break;
						}
							
				}
				else
					setViewAlert(service_data_displayListService.get(position), null);
			}
		});
		
		loadDataTask = new LoadDataTask();
		
		scrollListener = new EndlessScrollListener() {
			
			@Override
			protected void onLoadMoreData(int page) {
				if (loadDataTask.getStatus() != AsyncTask.Status.RUNNING)
				{
					loadDataTask = new LoadDataTask();
					loadDataTask.execute();
				}
			}
			
			@Override
			protected boolean hasMoreDataToLoad() {
				if (service_data_displayListService.size() > service_data_loading.size())
					return true;
				return false;
			}
		};		
		
		listViewItemCamera.setOnScrollListener(scrollListener);



		category_data_original.clear();
		for (CategoryDTO category : category_data)
			category_data_original.add(category);

		listViewCategoryCamera = (Gallery) findViewById(R.id.listViewCategoryCamera);
		categoryAdapter = new CategoryAdapter(this, R.layout.listview_category_camera, category_data, listViewCategoryCamera);
		listViewCategoryCamera.setAdapter(categoryAdapter);

		/*
		 * Load checkBox value (True/ False) in categoryAdapter
		 */
		if (category_selected.get(1) && category_selected.get(2) && category_selected.get(3)
				&&category_selected.get(4) && category_selected.get(5)
				&&category_selected.get(6) && category_selected.get(7))
			categoryAdapter.bool_checkBox_selection.set(0, true);
		else
		{
			categoryAdapter.bool_checkBox_selection.set(1, category_selected.get(1));
			categoryAdapter.bool_checkBox_selection.set(2, category_selected.get(2));
			categoryAdapter.bool_checkBox_selection.set(3, category_selected.get(3));
			categoryAdapter.bool_checkBox_selection.set(4, category_selected.get(4));
			categoryAdapter.bool_checkBox_selection.set(5, category_selected.get(5));
			categoryAdapter.bool_checkBox_selection.set(6, category_selected.get(6));
			categoryAdapter.bool_checkBox_selection.set(7, category_selected.get(7));
		}
		
		listViewCategoryCamera.setOnItemClickListener(new OnItemClickListener() {

					public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
						CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkBox_category_camera);
						if (checkBox.isChecked())
						{
							checkBox.setChecked(false);
							categoryAdapter.bool_checkBox_selection.set(position, false);
							if (position == 0)
							{
								category_selected.put(1, false);
								category_selected.put(2, false);
								category_selected.put(3, false);
								category_selected.put(4, false);
								category_selected.put(5, false);
								category_selected.put(6, false);
								category_selected.put(7, false);
							}
							else
								category_selected.put(position, false);
						}
						else 
						{
							checkBox.setChecked(true);
							categoryAdapter.bool_checkBox_selection.set(position, true);
							if (position == 0)
							{
								category_selected.put(1, true);
								category_selected.put(2, true);
								category_selected.put(3, true);
								category_selected.put(4, true);
								category_selected.put(5, true);
								category_selected.put(6, true);
								category_selected.put(7, true);
							}
							else
							{
								if (categoryAdapter.bool_checkBox_selection.get(0) == true)
								{
									category_selected.put(1, false);
									category_selected.put(2, false);
									category_selected.put(3, false);
									category_selected.put(4, false);
									category_selected.put(5, false);
									category_selected.put(6, false);
									category_selected.put(7, false);
								}	
								category_selected.put(position, true);
							}
								
						}

						if (position == 0) // All service type
						{
							// clear check in category items
							for (int i = 1; i < categoryAdapter.bool_checkBox_selection.size(); i++)
								categoryAdapter.bool_checkBox_selection.set(i, false);
							categoryAdapter.notifyDataSetChanged();
							
							service_data_displayListService.clear();
							service_data_displayServiceIcon.clear();
							service_data_loading.clear();
							service_data_displayListService.addAll(service_data_original);
							service_data_displayServiceIcon.addAll(service_data_original);
							
							DisplayServicesWithOrientation();
						}
						else // Custom service type
						{
							// clean check in All services (category item)
							categoryAdapter.bool_checkBox_selection.set(0, false);
							categoryAdapter.notifyDataSetChanged();

							service_data_displayListService.clear();
							service_data_displayServiceIcon.clear();
							service_data_loading.clear();
							for (ServiceDTO i : service_data_original) 
							{
								for (int j = 1; j < categoryAdapter.bool_checkBox_selection.size(); j++) 
								{
									// the type of service is checked
									if (i.getCategoryId() == j
											&& categoryAdapter.bool_checkBox_selection.get(j).booleanValue() == true)
									{
										service_data_displayListService.add(i);
										service_data_displayServiceIcon.add(i);
									}
								}
							}
							
							DisplayServicesWithOrientation();
						}
					}
				
		});

		// Get location
		// //---------------------------------------------------------------------------------------

		LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		String bestProvider = locationManager.getBestProvider(criteria, true);

		locationManager.requestLocationUpdates(bestProvider, 1, 1, new GeoUpdateHandler(this));
		
		if (autoUpdateLocation == true)
		{
			try {
				Location location = locationManager.getLastKnownLocation(bestProvider);
				OrientationHelper.setCurLatLon(location.getLatitude(), location.getLongitude());				
			} catch (Exception ex) {
	
			}
		}

		/**
		 * Kalman Filter
		 */
		if (isCompass == true) {
			sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
			km0 = new KalmanState(1, 5, 2, 0); // Loc Kalman
			km1 = new KalmanState(1, 5, 2, 0); // Loc Kalman
			km2 = new KalmanState(1, 5, 2, 0); // Loc Kalman

			updateOrientation(new float[] { 0, 45, 45 });
		}

		/**
		 * Display CheckBox Discount_Information
		 */
		if (bool_discount_information == false)
		{
			LinearLayout linearLayout_discount_information = (LinearLayout) findViewById(R.id.linearLayout_discount_information);
			linearLayout_discount_information.setVisibility(View.GONE);
		}
		
		CheckBox checkBox_discount_information = (CheckBox) findViewById(R.id.checkBox_discount_information);
		checkBox_discount_information.setChecked(bool_discount_information);
		checkBox_discount_information.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if (isChecked == false)
				{
					LinearLayout linearLayout_discount_information = (LinearLayout) findViewById(R.id.linearLayout_discount_information);
					linearLayout_discount_information.setVisibility(View.GONE);
					bool_discount_information = false;
					
					GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
					SortServices(service_data_original, new AscendingComparatorByDistance());

					service_data_displayListService.clear();
					service_data_displayServiceIcon.clear();
					service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
					service_data_displayServiceIcon.addAll(service_data_displayListService);
					service_data_loading.clear();
					itemAdapter.updateArrayList(service_data_loading);
					itemAdapter.notifyDataSetChanged();
					
				}
			}
		});
		
		//First Use
		downloadDataInTheFirstUse(firsTimetUse);
		Log.i("MainActivity", "[onCreate] Finish Create");
		
		DisplayServicesWithOrientation();
	}
	
	private void loadData()
	{
		pd_downloadServices = ProgressDialog.show(MainActivity.this, "Load data", "Loading... please wait", true);
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
				//SortServices(service_data_original, new AscendingComparatorByDistance());
				pd_downloadServices.dismiss();
			}
		});

		pd_downloadServices.setOnDismissListener(new OnDismissListener() {
			@Override
			public void onDismiss(DialogInterface dialog) {
				try 
				{
					ArrayList<ServiceDTO> list = new ArrayList<ServiceDTO>();
					list = GetServicesByCategory(service_data_original, category_selected);
					service_data_displayListService.clear();					
					service_data_displayListService.addAll(list);
					service_data_displayServiceIcon.clear();
					service_data_displayServiceIcon.addAll(list);
				}
				catch (Exception ex) {
				}
			}
		});

		t.start();
	}
	
	private void downloadDataInTheFirstUse(Boolean fist_use)
	{
		if (fist_use == true)
		{
			caDB.open();
			if (caDB.valueExistsByName("Hotel") == false)
				caDB.insertCategory("Hotel");
			if (caDB.valueExistsByName("Restaurant") == false)
				caDB.insertCategory("Restaurant");
			if (caDB.valueExistsByName("ATM") == false)
				caDB.insertCategory("ATM");
			if (caDB.valueExistsByName("Hospital") == false)
				caDB.insertCategory("Hospital");
			if (caDB.valueExistsByName("Bookstore") == false)
				caDB.insertCategory("Bookstore");
			if (caDB.valueExistsByName("Karaoke") == false)
				caDB.insertCategory("Karaoke");
			if (caDB.valueExistsByName("School") == false)
				caDB.insertCategory("School");
			caDB.close();
			
			new AlertDialog.Builder(context)
			.setIcon(android.R.drawable.ic_dialog_info)
			.setTitle("The First Time Use")
			.setMessage("Do you want to download services data?")
			.setPositiveButton("Yes", new DialogInterface.OnClickListener() {						
				@Override
				public void onClick(DialogInterface dialog, int which) {
					if (NetworkHelper.isNetworkAvailable(MainActivity.this) == false)
					{
						Toast.makeText(
								getApplicationContext(),
								"No network connection. Please check your connection settings and try again",
								Toast.LENGTH_LONG).show();
						Editor editor = prefs.edit();
					    editor.putBoolean(Constants.firsTimetUse, true);
					    editor.commit();
					    return;
					}
					pd_downloadServices = ProgressDialog.show(MainActivity.this, "Download", "Downloading... please wait", true);
					Thread t = new Thread(new Runnable() {
						@Override
						public void run() {
							try 
							{
								DbServiceHelper sH = new DbServiceHelper();
								ArrayList<ServiceDTO> listServicesDTO = new ArrayList<ServiceDTO>();
								// listServicesDTO = sH.getAllServices();
								listServicesDTO = sH.getServicesInDistance(OrientationHelper.getCurLat(), OrientationHelper.getCurLon(), distance_max);

								service_data_displayListService.clear();

								iDB.open();
								for (int i = 0; i < listServicesDTO.size(); i++)
								{
									if (iDB.valueExistsByID(listServicesDTO.get(i).getId()) == false)
									{
										iDB.insertItem(listServicesDTO.get(i));
										service_data_original.add(listServicesDTO.get(i));
									}
									else 
									{
										iDB.updateItem(listServicesDTO.get(i));
										service_data_original.add(listServicesDTO.get(i));
									}
								}
								iDB.close();
							}
							catch (Exception ex) 
							{

							}
							pd_downloadServices.dismiss();
						}
					});

					pd_downloadServices.setOnDismissListener(new OnDismissListener() {
						@Override
						public void onDismiss(DialogInterface dialog) {
							try 
							{
								Editor editor = prefs.edit();
							    editor.putBoolean(Constants.firsTimetUse, false);
							    editor.commit();
								GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
								service_data_displayListService.clear();
								service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
								service_data_displayServiceIcon.clear();
								service_data_displayServiceIcon.addAll(service_data_displayListService);
								service_data_loading.clear();
								itemAdapter.updateArrayList(service_data_loading);
								itemAdapter.notifyDataSetChanged();
							}
							catch (Exception ex) {
							}
						}
					});

					t.start();

				}
			} )
			.setNegativeButton("No", new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Editor editor = prefs.edit();
				    editor.putBoolean(Constants.firsTimetUse, false);
				    editor.commit();
					dialog.dismiss();
				}
			})
			.show();
		}
	}

	private void setViewAlert(final ServiceDTO service, final SubItemDTO subItem) {
		Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("Choice View");
		final String[] selectFruit = { "Google Map View", "Details", "Interact View"};
		builder.setItems(selectFruit, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
				case 0:
				{
					Intent myIntent = new Intent(MainActivity.this, GoogleMapActivity.class);
					myIntent.putExtra("serviceItem", service);
					myIntent.putExtra("state_of_googlemap", Constants.STATE_GOOGLEMAP_DISPLAY_ONE_SERVICE);
					startActivity(myIntent);
					break;
				}
				case 1:
				{
					Intent myIntent = new Intent(MainActivity.this, DetailActivity.class);
					myIntent.putExtra("serviceItem", service);
					myIntent.putExtra("subItem", subItem);
					startActivity(myIntent);
					break;
				}
				case 2:
				{
					preview.DestroyCamera();
					Intent myIntent = new Intent(MainActivity.this, InteractActivity.class);
					myIntent.putExtra("serviceItem", service);					
					startActivity(myIntent);
					break;
				}
				default:
					break;
				}
				dialog.dismiss();
			}
		});
		builder.setNegativeButton("Cancel",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				});
		AlertDialog alert = builder.create();
		alert.show();
	}

	private void SortServices(ArrayList<ServiceDTO> list, myapp.sortStategy.Comparator _comparator) 
	{
		for (int i = 0; i < list.size(); i++)
			for (int j = i; j < list.size(); j++) 
			{
				if (_comparator.Compare(list.get(i), list.get(j)))
				{
					ServiceDTO s = list.get(i);
					list.set(i, list.get(j));
					list.set(j, s);
				}
			}
	}

	private void DisplayServicesWithOrientation() {
		ArrayList<ServiceDTO> listServicesDTO = new ArrayList<ServiceDTO>();

		if (autoFilterServicesByOrientation) // Loc danh sach service theo huong
		{
			if (displayServiceIcon == true) // Hien thi danh sach service dang icon tren man hinh
			{
				listServicesDTO = OrientationHelper.getServicesByOrientation(OrientationHelper.getCurLon(),
						OrientationHelper.getCurLat(),
						service_data_displayServiceIcon, 
						oldAngleValues[0],
						Constants.DEGREE_VIEW);

				if (service_data_displayListService.size() != 0)
				{
					service_data_displayListService.clear();
					itemAdapter.updateArrayList(service_data_displayListService);
					itemAdapter.notifyDataSetChanged();
				}
				myDraw.clearItems();
				ArrayList<ServiceDTO> items = new ArrayList<ServiceDTO>();
				items.addAll(listServicesDTO);
				// myDraw.add();
				for (int i = 0; i < items.size(); i++) 
				{
					DisplayMetrics displayMetrics = new DisplayMetrics();
					getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

					myDraw.addMovableItem(items.get(i),
							OrientationHelper.getCurLat(),
							OrientationHelper.getCurLon(),
							displayMetrics.widthPixels / 2,
							displayMetrics.heightPixels * 3 / 4, 
							oldAngleValues[0],
							Constants.DEGREE_VIEW);
				}
				myDraw.invalidate();
			}
			else // Hien thi danh sach service theo dang list
			{
				listServicesDTO = OrientationHelper.getServicesByOrientation(OrientationHelper.getCurLon(),
								OrientationHelper.getCurLat(),
								service_data_displayServiceIcon, 
								oldAngleValues[0],
								Constants.DEGREE_VIEW);
	
				service_data_displayListService.clear();
				service_data_displayListService.addAll(listServicesDTO);
				//service_data_loading.clear();
				itemAdapter.updateArrayList(service_data_displayListService);
				itemAdapter.notifyDataSetChanged();
			}
		}
		else //Hien thi danh sach service
		{
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
		}
	}
	
	
	// Compass
	/**
	 * 
	 * @param values 
	 *  Yaw(values[0]); A yaw is a counterclockwise rotation of Alpha about the z-axis
    	Pitch(values[1]); A pitch is a counterclockwise rotation of Beta about the x-axis
    	Roll(values[2]); A roll is a counterclockwise rotation of Gamma about the y-axis
	 */
	private void updateOrientation(float[] values) {
		if (autoChangeScreen == true && Math.abs(values[1]) <= 10
				&& changeIntent == true) 
		{
			
			changeIntent = false;
			Intent myIntent = new Intent(MainActivity.this, GoogleMapActivity.class);
			myIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			myIntent.putExtra("state_of_googlemap", Constants.STATE_GOOGLEMAP_DISPLAY_LIST_SERVICE);
			startActivity(myIntent);
		}

		if (autoFilterServicesByOrientation == true)
		{
			float angle = Math.abs(values[0] - oldAngleValues[0]);

			if (angle > 5f) 
			{
				oldAngleValues[0] = values[0];
				oldAngleValues[1] = values[1];
				oldAngleValues[2] = values[2];

				DisplayServicesWithOrientation();
			}
		}
	}

	private final SensorEventListener sensorEventListener = new SensorEventListener() {
		public void onSensorChanged(SensorEvent event) {
			boolean flag = false;

			// Kiểm tra sự thay đổi của sensor ACCELEROMETER
			// và MAGNETIC_FIELD
			switch (event.sensor.getType()) 
			{
			case Sensor.TYPE_ACCELEROMETER:
				for (int i = 0; i < 3; i++)
					aValues[i] = event.values[i];
				flag = true;
				break;
			case Sensor.TYPE_MAGNETIC_FIELD:
				for (int i = 0; i < 3; i++)
					mValues[i] = event.values[i];			
				flag = true;
				break;
			}

			if (flag == true) 
			{

				float[] values = new float[3];
				float[] R = new float[9];
				float[] outR = new float[9];

				// Lay Rotation Matrix => R
				boolean success = SensorManager.getRotationMatrix(R, null, aValues, mValues);

				// Thay doi he truc khi quay thiet bi di dong
				if (success) {
					String windoSrvc = Context.WINDOW_SERVICE;
					WindowManager wm = ((WindowManager) getSystemService(windoSrvc));
					Display display = wm.getDefaultDisplay();
					int rotation = display.getRotation();

					((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();

					int x_axis = SensorManager.AXIS_X;
					int y_axis = SensorManager.AXIS_Y;
					switch (rotation)
					{
					case (Surface.ROTATION_90):
						x_axis = SensorManager.AXIS_Y;
						y_axis = SensorManager.AXIS_MINUS_X;
						break;
					case (Surface.ROTATION_180):
						y_axis = SensorManager.AXIS_MINUS_Y;
						break;
					case (Surface.ROTATION_270):
						x_axis = SensorManager.AXIS_MINUS_Y;
						y_axis = SensorManager.AXIS_X;
						break;
					default:
						break;
					}

					SensorManager.remapCoordinateSystem(R, x_axis, y_axis, outR);

					// R = Rz * Rx * Ry
					double yaw, roll, pitch;

					// Gimbal lock khi Pitch gần đạt +/-90 độ
					// Sin(Pitch) gần đạt giá trị +/-1
					if (outR[7] > 0.9) //-Sin(Pitch) ~ 0.9
					{ 
						yaw = Math.atan2(-outR[3], outR[0]);
						pitch = -Math.PI / 2;
						roll = 0;
						values[1] = (float) (pitch / Math.PI * 180);
						values[2] = (float) (roll / Math.PI * 180);
						values[0] = (float) (yaw / Math.PI * 180);
					}
					else if (outR[7] < -0.9) //-Sin(Pitch) ~ -0.9
					{ 
						yaw = Math.atan2(-outR[3], outR[0]);
						pitch = Math.PI / 2;
						roll = 0;
						values[1] = (float) (pitch / Math.PI * 180);
						values[2] = (float) (roll / Math.PI * 180);
						values[0] = (float) (yaw / Math.PI * 180);
					} 
					else 
					{
						yaw = Math.atan2(outR[1], outR[4]);
						pitch = -Math.asin(outR[7]);
						roll = Math.atan2(outR[6], outR[8]);
						values[0] = (float) (yaw / Math.PI * 180);
						values[1] = (float) (pitch / Math.PI * 180);
						values[2] = (float) (roll / Math.PI * 180);
					}

					// Kalman Filter
					
					km0.update(values[0]); 
					values[0] = (float)km0.getX();
					km1.update(values[1]); 
					values[1] = (float)km1.getX();
					km2.update(values[2]); 
					values[2] = (float)km2.getX();

					//Log.i("updateOrientation_Main", String.valueOf(values[1]));
					// Update huong cua compass & yeu cau draw lai compass
					updateOrientation(values);
				}
			}
		}

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}
	};

	@Override
	protected void onResume() {
		Log.i("camera - resume", "Resume");
		super.onResume();
		
		updateFromPreferences();
		myDraw.clearItems();

		/**
		 * Update listView
		 */
		if (autoFilterServicesByOrientation == false) 
		{
			loadData();
			service_data_loading.clear();
			itemAdapter = new ItemAdapter(this, R.layout.listview_item_camera, service_data_loading, subItems_data, bool_discount_information);
			listViewItemCamera.setAdapter(itemAdapter);
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();			
			itemAdapter.notifyDataSetChanged();			
		}
		else
		{
			itemAdapter = new ItemAdapter(this, R.layout.listview_item_camera, service_data_displayListService, subItems_data, bool_discount_information);
			listViewItemCamera.setAdapter(itemAdapter);
		}			

		/**
		 * Register Sensor
		 */
		changeIntent = true;
		if (isCompass == true)
		{
			Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
			Sensor magField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

			sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
			sensorManager.registerListener(sensorEventListener, magField, SensorManager.SENSOR_DELAY_FASTEST);
		}
	}

	@Override
	protected void onStop() {
		if (isCompass == true) 
			sensorManager.unregisterListener(sensorEventListener);
		super.onStop();
//		XmppConnection.ProcessOnDestroyOrStop();
	}
	
	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		Log.i("CameraActivity", "OnPause");
		super.onPause();
		if (pd_downloadSubItem != null)
			pd_downloadSubItem.dismiss();
		if (pd_downloadServices != null)
			pd_downloadServices.dismiss();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		XmppConnection.ProcessOnDestroyOrStop();
	}


	private void updateFromPreferences() {
		Context context = getApplicationContext();
		prefs = PreferenceManager.getDefaultSharedPreferences(context);

		autoChangeScreen = prefs.getBoolean(Constants.autoChangeScreen, false);
		autoFilterServicesByOrientation = prefs.getBoolean(Constants.autoFilterServicesByOrientation, false);
		displayServiceIcon = prefs.getBoolean(Constants.displayServiceIcon, false);
		autoUpdateLocation = prefs.getBoolean(Constants.autoUpdateLocation, true);
		firsTimetUse = prefs.getBoolean(Constants.firsTimetUse, true);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) 
		{
		case R.id.search: 
		{
			Intent myIntent = new Intent(MainActivity.this, SearchActivity.class);
			startActivity(myIntent);
			return true;
		}

		// MenuGroup: Distance
		case R.id.db100m: 
		{
			distance_min = 0;
			distance_max = 100;
			item.setChecked(true);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();			
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);
			
			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}

		case R.id.db200m: 
		{
			distance_min = 100;
			distance_max = 200;
			item.setChecked(true);
			myDraw.setMaxDistance(distance_max);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);

			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}

		case R.id.db500m: 
		{
			distance_min = 200;
			distance_max = 500;
			item.setChecked(true);
			myDraw.setMaxDistance(distance_max);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);

			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}
		
		case R.id.db1000m: 
		{
			distance_min = 500;
			distance_max = 1000;
			item.setChecked(true);
			myDraw.setMaxDistance(distance_max);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);

			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}
		
		case R.id.db2000m: 
		{
			distance_min = 1000;
			distance_max = 2000;
			item.setChecked(true);
			myDraw.setMaxDistance(distance_max);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);

			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}
		
		case R.id.db5000m: 
		{
			distance_min = 2000;
			distance_max = 5000;
			item.setChecked(true);
			myDraw.setMaxDistance(distance_max);

			GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
			service_data_displayListService.clear();
			service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
			service_data_displayServiceIcon.clear();
			service_data_displayServiceIcon.addAll(service_data_displayListService);

			service_data_loading.clear();
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			return true;
		}
		
		case R.id.sort_by_distance:
		{
			comparator = new AscendingComparatorByDistance();
			item.setChecked(true);
			SortServices(service_data_original, comparator);
			SortServices(service_data_displayListService, comparator);
			itemAdapter.updateArrayList(service_data_displayListService);
			itemAdapter.notifyDataSetChanged();
			return true;
		}

		case R.id.sort_by_name: 
		{
			comparator = new AscendingComparatorByName();
			item.setChecked(true);
			SortServices(service_data_original, comparator);
			SortServices(service_data_displayListService, comparator);
			itemAdapter.updateArrayList(service_data_displayListService);
			itemAdapter.notifyDataSetChanged();
			return true;
		}

		case R.id.sort_by_category: 
		{
			comparator = new AscendingComparatorByCategory();
			item.setChecked(true);
			SortServices(service_data_original, comparator);
			SortServices(service_data_displayListService, comparator);
			itemAdapter.updateArrayList(service_data_displayListService);
			itemAdapter.notifyDataSetChanged();
			return true;
		}

		// Menu: Google map
		case R.id.googlemap: 
		{
			Intent myIntent = new Intent(MainActivity.this, GoogleMapActivity.class);
			myIntent.putExtra("state_of_googlemap", Constants.STATE_GOOGLEMAP_DISPLAY_LIST_SERVICE);
			startActivity(myIntent);
			return true;
		}

		case R.id.download: 
		{
			pd_downloadServices = ProgressDialog.show(this, "Download", "Downloading... please wait", true);
			Thread t = new Thread(new Runnable() {
				@Override
				public void run() {
					try 
					{
						DbServiceHelper sH = new DbServiceHelper();
						ArrayList<ServiceDTO> listServicesDTO = new ArrayList<ServiceDTO>();
						// listServicesDTO = sH.getAllServices();
						listServicesDTO = sH.getServicesInDistance(OrientationHelper.getCurLat(), OrientationHelper.getCurLon(), distance_max);

						service_data_displayListService.clear();

						iDB.open();
						for (int i = 0; i < listServicesDTO.size(); i++)
						{
							if (iDB.valueExistsByID(listServicesDTO.get(i).getId()) == false)
							{
								iDB.insertItem(listServicesDTO.get(i));
								service_data_original.add(listServicesDTO.get(i));
							}
							else 
							{
								iDB.updateItem(listServicesDTO.get(i));
								service_data_original.add(listServicesDTO.get(i));
							}
						}
						iDB.close();
					}
					catch (Exception ex) 
					{
						if (isNetworkAvailable() == false)
						{
							Toast.makeText(
									getApplicationContext(),
									"No network connection. Please check your connection settings and try again",
									Toast.LENGTH_LONG).show();
						}
					}
					pd_downloadServices.dismiss();
				}
			});

			pd_downloadServices.setOnDismissListener(new OnDismissListener() {
				@Override
				public void onDismiss(DialogInterface dialog) {
					// TODO Auto-generated method stub
					try 
					{
						GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
						service_data_displayListService.clear();
						service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));

						service_data_displayServiceIcon.clear();
						service_data_displayServiceIcon.addAll(service_data_displayListService);
						
						service_data_loading.clear();
						itemAdapter.updateArrayList(service_data_loading);
						itemAdapter.notifyDataSetChanged();
					}
					catch (Exception ex) {
					}
				}
			});

			t.start();
			return true;
		}

		case R.id.chat: {
			Intent myIntent = new Intent(MainActivity.this, XmppClient.class);
			startActivity(myIntent);
			return true;
		}

		case R.id.add_service: {
			Intent myIntent = new Intent(MainActivity.this, AddNewServiceActivity.class);
			startActivity(myIntent);		
			return true;
		}

		case R.id.get_discount_information: {
			pd_downloadSubItem = ProgressDialog.show(this, "Download", "Downloading... please wait", true);
			Thread t = new Thread(new Runnable() {
				@Override
				public void run() {
					try 
					{
						DbServiceHelper dbsh = new DbServiceHelper();
						subItems_data = dbsh.getAllSubItems();
					} 
					catch (Exception ex) 
					{
						// if (isNetworkAvailable() == false)
						{
							Toast.makeText(
									getApplicationContext(),
									"No network connection. Please check your connection settings and try again",
									Toast.LENGTH_LONG).show();
						}
					}
					pd_downloadSubItem.dismiss();
				}
			});

			pd_downloadSubItem.setOnDismissListener(new OnDismissListener() {
				@Override
				public void onDismiss(DialogInterface dialog) {
					// TODO Auto-generated method stub
					try
					{
						if (subItems_data != null)
						{
							itemAdapter.addAllSubItems(subItems_data);
							itemAdapter.setDiscountInformation(true);
							bool_discount_information = true;

							GetServicesByDistance(service_data_original, distance_min, distance_max, comparator, iDB);
							service_data_displayListService.clear();
							service_data_displayListService.addAll(GetServicesByCategory(service_data_original, category_selected));
							
							service_data_displayServiceIcon.clear();
							service_data_displayServiceIcon.addAll(service_data_displayListService);
							service_data_loading.clear();
							
							itemAdapter.updateArrayList(service_data_loading);
							itemAdapter.notifyDataSetChanged();
							LinearLayout linearLayout_discount_information = (LinearLayout) findViewById(R.id.linearLayout_discount_information);
							linearLayout_discount_information.setVisibility(View.VISIBLE);
							CheckBox checkBox_discount_information = (CheckBox) findViewById(R.id.checkBox_discount_information);
							checkBox_discount_information.setChecked(true);
						}
					}
					catch (Exception ex) {
					}
				}
			});

			t.start();
			return true;
		}

		case R.id.Camerasettings: {
			Intent i = new Intent(MainActivity.this, Settings.class);
			startActivity(i);
			return true;
		}

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private boolean isNetworkAvailable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		if (connectivityManager != null)
		{
			NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
			return activeNetworkInfo != null && activeNetworkInfo.isConnected();
		}
		return false;
	}

	private class LoadDataTask extends AsyncTask<Void, Void, Void> {
		ArrayList<ServiceDTO> temp_services;
		@Override
		protected Void doInBackground(Void... params) {

			if (isCancelled()) {
				return null;
			}
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                	mFooterView.setVisibility(View.VISIBLE);
                	mProgressBarLoadMore.setVisibility(ProgressBar.VISIBLE);
                }
            });

			// Simulates a background task
			try {				
				Thread.sleep(300);
			} catch (InterruptedException e) {
			}
			


			int visibleThreshold = (service_data_loading.size() + Constants.VISIBLE_THRESHOLD < service_data_displayListService.size())
					?Constants.VISIBLE_THRESHOLD
					:service_data_displayListService.size()-service_data_loading.size();
			temp_services = new ArrayList<ServiceDTO>();
			temp_services.addAll(service_data_loading);
	        Log.i("doInBackground_service_data.size()", String.valueOf(service_data_displayListService.size()));
	        Log.i("doInBackground_service_data_loading.size()", String.valueOf(service_data_loading.size()));
	        Log.i("doInBackground_visibleThreshold", String.valueOf(visibleThreshold));
	        
			for (int i = service_data_loading.size(); i < service_data_loading.size()+ visibleThreshold; i++)
				temp_services.add(service_data_displayListService.get(i));


			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			if (mFooterView != null)
			mFooterView.setVisibility(View.GONE);
			mProgressBarLoadMore.setVisibility(ProgressBar.GONE);

			service_data_loading.clear();
			service_data_loading.addAll(temp_services);
			itemAdapter.updateArrayList(service_data_loading);
			itemAdapter.notifyDataSetChanged();
			scrollListener.onLoadingComplete();
			super.onPostExecute(result);
		}

		@Override
		protected void onCancelled() {
			// Notify the loading more operation has finished
			scrollListener.onLoadingComplete();
		}
	}
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		// TODO Auto-generated method stub
		
	    int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
		preview.setDegreeOrientation(rotation);
		super.onConfigurationChanged(newConfig);
	}

	private ArrayList<ServiceDTO> GetServicesByCategory(ArrayList<ServiceDTO> _lservices, SparseBooleanArray _categorys)
	{
		/*
		 * Filter by categoty
		 */
		ArrayList<ServiceDTO> list = new ArrayList<ServiceDTO>();
		for (ServiceDTO s : _lservices)
			for (int i = 0; i < _categorys.size(); i++)
				if(s.getCategoryId() == _categorys.keyAt(i) && _categorys.valueAt(i) == true)
					list.add(s);
					
		return list;
	}
	private void GetServicesByDistance(ArrayList<ServiceDTO> _lservices, int _distance_min, int _distance_max ,Comparator _comparator, ItemDB itemDB) {
		//Get services in local database
		ArrayList<ServiceDTO> list = new ArrayList<ServiceDTO>();
		try
		{
			itemDB.open();
			list = itemDB.getAllServices();
			itemDB.close();
		}catch(Exception e){}	

		/*
		 * Filter by discount information
		 */
		if (bool_discount_information == true) 
		{
			ArrayList<ServiceDTO> serviceList = new ArrayList<ServiceDTO>();
			serviceList.addAll(list);

			list.clear();
			for (int i = 0; i < serviceList.size(); i++) 
			{
				boolean flag = false;
				for (SubItemDTO sub : subItems_data)
					if (serviceList.get(i).getId() == sub.serviceId)
						flag = true;

				if (flag == true)
					list.add(serviceList.get(i));
			}
		}
		
		/*
		 * Filter by distance
		 */
		_lservices.clear();
		for (int i = 0; i < list.size(); i++)
		{
			double distance =  OrientationHelper.CalculateDistanceBetweenTwoPoints(OrientationHelper.getCurLon(), OrientationHelper.getCurLat(), list.get(i).getLongitude(), list.get(i).getLatitude());
			if (_distance_min <= distance && distance < _distance_max)
				_lservices.add(list.get(i));
		}
		SortServices(_lservices, _comparator);

	}

	public class GeoUpdateHandler implements LocationListener {

		//private Context mContext;

		public GeoUpdateHandler(Context context) {
			//mContext = context;
		}

		// ------
		public void onLocationChanged(Location location) {
			if (autoUpdateLocation)
			{
				OrientationHelper.setCurLatLon(location.getLatitude(), location.getLongitude());
			}
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {

		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

	}

}
